package com.open.base.interceptor;


import com.open.common.annotation.MethodPermission;
import com.open.base.model.Menu;
import com.open.common.constants.SysCode;
import com.open.base.model.LoginUser;
import com.open.base.utils.UserHolderUtils;
import com.open.common.utils.StringUtils;
import com.open.common.utils.ThrowUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 权限拦截器
 * @author dashu03
 * @date 2025年02月15日 11:02
 */
@Component
@Slf4j
public class PermissionInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //校验登录对象是否过期
        LoginUser loginUser = UserHolderUtils.getLoginUser();
        if (StringUtils.isNull(loginUser)) {
            log.error("请求接口地址：{} 失败，登录过期请重新登录", request.getRequestURI());
        }
        ThrowUtils.throwIf(StringUtils.isNull(loginUser), "登录过期请重新登录", SysCode.UNAUTHORIZED);
        //校验权限
        //检查处理程序是否为 HandlerMethod 的实例
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        //检查方法是否标记了 MethodPermission 注解
        if (!method.isAnnotationPresent(MethodPermission.class)) {
            return true;
        }
        MethodPermission methodPermission = method.getAnnotation(MethodPermission.class);
        List<String> permissions = loginUser.getPermissions().stream().map(Menu::getPermissionVal).collect(Collectors.toList());
        //如果没权限,直接抛异常,让全局业务异常捕获器捕获,返回对应的状态码
        ThrowUtils.throwIf(!hasThisPrivilege(permissions, methodPermission.value()), "无权限，请联系管理员授权", SysCode.FORBIDDEN);
        return true;
    }

    public boolean hasThisPrivilege(List<String> strPrivilege, String privilegeCode) {
        if (strPrivilege == null || strPrivilege.isEmpty()) {
            return false;
        }
        return strPrivilege.contains(privilegeCode);
    }

    // 响应体尚未生成（消息转换或视图渲染未执行）
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView){}

    // 响应已发送，输出流已关闭
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex){}
}
